package iedcyt.acute.dataAccess.utils;

import iedcyt.acute.dataAccess.factories.AbsFactoryDao;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Clase que ofrece servicios para la modificacion del fichero beans.xml y la inicializacion del 
 * acceso a las bases de datos
 * @author 53385255R
 *
 */
public class BeansXML {

	private final Logger _log = Logger.getLogger(BeansXML.class);
	
	private static BeansXML _instance;
	
	private File _file;
	private Document _doc;
	
	/**
	 * Patron observador
	 */
	private List<AbsFactoryDao> _daoFactories;
	
	/**
	 * Registro de factorias para implementacion del patron observador, y que puedan modificarse las rutas de la base de datos
	 * durante la ejecucion del programa
	 * @param fact
	 */
	public void registerFactoryDao(AbsFactoryDao fact) {
		_daoFactories.add(fact);
	}
	
	/**
	 * Singleton method
	 * @return instancia unica de la clase
	 */
	public static BeansXML getInstance()
	{
		if (_instance == null)
			_instance = new BeansXML();
		
		return _instance;
	}
	
	/**
	 * Constructor privado para Singleton
	 * 
	 * Accede al fichero de beans con la configuracion de las bases de datos e inicializa el 
	 * contenedor de factorias
	 */
private BeansXML() {
  try {
	  _file = new File(Parameters.get_instance().getBeanFile());
	  DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
	  DocumentBuilder db = dbf.newDocumentBuilder();
	  _doc = db.parse(_file);
	  _doc.getDocumentElement().normalize();
	  _daoFactories = new ArrayList<AbsFactoryDao>();
  } catch (Exception e) {
	  _log.error("Error al acceder al fichero beans.xml");
	  _log.error(e);
  }
}
 
 /**
  * Obtiene el path de la base de datos indicada
  * @param dbId identificador de la base de datos
  * @return ruta de la base de datos indicada en el dbId
  */
 public String getDatabasePath(String dbId)
 {
	
 String path = "";
 try
 {
	 NodeList nodeLst = _doc.getElementsByTagName("bean");
	  for (int s = 0; s < nodeLst.getLength(); s++) {

	    Node fstNode = nodeLst.item(s);
	    
	    if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
	  
	           Element fstElmnt = (Element) fstNode;
	        
	           NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("property");
	      
	           if (fstElmnt.getAttribute("id").toLowerCase().equals(dbId.toLowerCase())) {
	        	   for (int i = 0; i < fstNmElmntLst.getLength(); i++) {
	        		   Element elmnt = (Element) fstNmElmntLst.item(i);
	        		   if (elmnt.getAttribute("name").toLowerCase().equals("url")) {
	        			   path = elmnt.getAttribute("value");
	        		   }
	      }
	           }
	    }
	  }
 } catch (Exception ex) {
	 _log.error("Error al obtener la ruta de la base de datos para : " + dbId);
 }
	    return path;
 }
 
 /**
  * Obtiene el path de la base de datos indicada
  * @param dbId identificador
 * 	@param path  ruta
  */
 public void setDatabasePath(String dbId, String path)
 {
	 

	 NodeList nodeLst = _doc.getElementsByTagName("bean");
	  for (int s = 0; s < nodeLst.getLength(); s++) {

	    Node fstNode = nodeLst.item(s);
	    
	    if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
	  
	           Element fstElmnt = (Element) fstNode;
	        
	           NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("property");
	      
	           if (fstElmnt.getAttribute("id").toLowerCase().equals(dbId.toLowerCase()))
	           {
	      for (int i = 0; i < fstNmElmntLst.getLength(); i++)
	      {
	    	  Element elmnt = (Element) fstNmElmntLst.item(i);
	    	  if (elmnt.getAttribute("name").toLowerCase().equals("url"))
	    	  {
	    		  elmnt.setAttribute("value", path);
	    	
	    	  }
	      }
	           }
	    }
	  }
	  

	
 }
 
 /**
  * Guarda los cambios que se hayan podido realizar.
  * Inicializa de nuevo los Daos
  * @return si se han guardado bien o no los cambios
  */
 public boolean saveChanges()
 {
	  try {
		  Transformer xformer = TransformerFactory.newInstance().newTransformer();
		xformer.transform
		      (new DOMSource(_doc), new StreamResult(_file));
		for (AbsFactoryDao fact : _daoFactories)
			fact.startDaos();
		
		return true;
	} catch (TransformerException e) {
		_log.error(e);
		return false;
	}
 }
}

